package com.code.pattern.factory.simplefactory;

import com.code.pattern.factory.ICourse;
import com.code.pattern.factory.JavaCourse;
import com.code.pattern.factory.PythonCourse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * 简单工厂类的实现；
 * 使用场景：当我们需要某个类的时候，这个类的初始化操作比较繁琐，那么只要我们用到就都会做一遍相同的初始化操作，
 *          那么就不够友好，对用户而言使用比较繁琐，所以我们把初始化操作交给工厂类创建，我们只需传入必要的参数即可获取想要的对象；
 *  简单工厂的缺点：当我需要新增一门课程的实现的时候，就需要修改工厂类，这也就违背了软件设计原则的开闭原则；
 * @author: liyufei
 * @date: 2021-03-13 13:25
 */
@Slf4j
public class CourseFactory {

    // 简单工厂方式一：
    // 通过字符串，这种容易把字符串写错
    public ICourse create(String course) {
        if ("java".equals(course)) {
            return new JavaCourse();
        } else if ("python".equals(course)) {   // 每新增一门课程的时候这里都需要新增工厂类代码
            return new PythonCourse();
        } else {
            return null;
        }
    }

    // 简单工厂方式二：
    /**
     * 可参考 LoggerFactory
     * @param className
     * @return
     */
    // 高级点的就是如下方式，通过反射来创建对象，只需把类全路径名传入即可，但是这种还是容易写错
    public ICourse createByClassName(String className) {
        try {
            if (StringUtils.isNotBlank(className)) {
                return (ICourse) Class.forName(className).newInstance();
            }
        } catch (Exception e) {
            log.error("对象创建失败", e);
        }
        return null;
    }

    // 简单工厂方式三：
    // 更高级写入，通过传入Class类型来创建对象
    public ICourse createByClass(Class clazz) {
        try {
            if (clazz != null) {
                return (ICourse) clazz.newInstance();
            }
        } catch (Exception e) {
            log.error("对象创建失败", e);
        }
        return null;
    }
}
